'''
Function:
    Define the l1 loss
Author:
    Zhenchao Jin
'''
import luojianet
import luojianet.nn as nn
import luojianet.ops as ops
from luojianet import nn, ops, Parameter, Tensor
from luojianet.ops import operations as P


'''
Function:
    L1Loss
Arguments:
    --prediction: prediction of the network
    --target: ground truth
    --scale_factor: scale the loss for loss balance
    --lowest_loss_value: added inspired by ICML2020, "Do We Need Zero Training Loss After Achieving Zero Training Error", https://arxiv.org/pdf/2002.08709.pdf
'''
def L1Loss(prediction, target, scale_factor=1.0, reduction='mean', lowest_loss_value=None):
    # calculate the loss
    # loss = F.l1_loss(prediction, target, reduction=reduction)
    loss = nn.L1Loss(reduction=reduction)(prediction, target)

    # scale the loss
    loss = loss * scale_factor
    # return the final loss
    if lowest_loss_value:
        # return torch.abs(loss - lowest_loss_value) + lowest_loss_value
        return ops.abs(loss - lowest_loss_value) + lowest_loss_value
    return loss